package cn.wokoba.service.strategy;


import cn.wokoba.service.strategy.armory.IStrategyDispatch;
import cn.wokoba.service.strategy.model.RaffleAwardEntity;
import cn.wokoba.service.strategy.model.RaffleFactorEntity;
import cn.wokoba.service.strategy.model.StrategyAwardEntity;
import cn.wokoba.service.strategy.repository.StrategyRepository;
import cn.wokoba.service.strategy.rule.chain.factory.DefaultChainFactory;
import cn.wokoba.service.strategy.rule.tree.DecisionTreeEngine;
import cn.wokoba.service.strategy.rule.tree.DefaultTreeFactory;
import cn.wokoba.types.enums.ResponseCode;
import cn.wokoba.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;

//抽奖策略抽象类，定义抽奖的标准流程
@Slf4j
public abstract class AbstractRaffleStrategy  {

    protected StrategyRepository repository;
    protected IStrategyDispatch strategyDispatch;
    // 抽奖的责任链 -> 从抽奖的规则中，解耦出前置规则为责任链处理
    protected final DefaultChainFactory defaultChainFactory;
    // 抽奖的决策树 -> 负责抽奖中到抽奖后的规则过滤，之后要做次数的判断和库存的扣减等。
    protected final DefaultTreeFactory defaultTreeFactory;


    public AbstractRaffleStrategy(DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory, StrategyRepository repository, IStrategyDispatch strategyDispatch) {
        this.defaultChainFactory = defaultChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
        this.repository = repository;
        this.strategyDispatch = strategyDispatch;
    }

    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        // 1. 参数校验
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if (null == strategyId || StringUtils.isBlank(userId)) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        // 2. 责任链抽奖计算,拿到初步的抽奖ID,黑名单、权重等直接返回抽奖结果
        DefaultChainFactory.StrategyAwardVO chainStrategyAwardVO = raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getLogicModel());
        if (!DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getLogicModel())) {
            return buildRaffleAwardEntity(strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getAwardRuleValue());
        }

        // 3. 规则树抽奖过滤,根据抽奖次数判断、库存判断、兜底兜里返回最终可获得奖品信息】
        DecisionTreeEngine.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(userId, strategyId, chainStrategyAwardVO.getAwardId(), raffleFactorEntity.getEndDateTime());
        log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());

        // 4. 返回抽奖结果
        return buildRaffleAwardEntity(strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());
    }

    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId, Integer awardId, String awardConfig) {
        StrategyAwardEntity strategyAward = repository.queryStrategyAwardEntity(strategyId, awardId);
        return RaffleAwardEntity.builder()
                .awardId(awardId)
                .awardTitle(strategyAward.getAwardTitle())
                .awardConfig(awardConfig)
                .sort(strategyAward.getSort())
                .build();

    }

   //抽奖计算，责任链抽象方法
    public abstract DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId);

    public abstract DecisionTreeEngine.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId);

   //抽奖结果过滤，决策树抽象方法
    public abstract DecisionTreeEngine.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime);

}
